home *** CD-ROM | disk | FTP | other *** search
/ Mac Mania 2 / MacMania 2.toast / Demo's / Tools&Utilities / Programming / FBSpriteWorld 1.05b / Project 1.01b / SWSpinningGlobe.main < prev    next >
Encoding:
Text File  |  1994-04-26  |  11.4 KB  |  319 lines  |  [TEXT/ZBAS]

  1. 'FBSpinningGlobe.main by Robert Hommel
  2. '© Copyright 1994
  3. 'All rights granted for any use whatsoever
  4.  
  5. 'This example program builds on the foundation of SWSimpleTest to
  6. 'create a more complex animation.  It demonstrates the use of Sprites
  7. 'with multiple Frames, the use of multiple Layers to produce a
  8. 'three-dimensional appearance, and inactive (non-mobile) Sprites.
  9.  
  10. 'You will notice a slight slowing of the animation as the Globe
  11. 'Sprites pass in front of or behind the SpriteWorld Text Sprite.
  12. 'FBSpriteWorld does rigorous checking to make sure that only those
  13. 'Sprites that have moved or changed frames are drawn.  Most of the
  14. 'time, the Text Sprite does not need to be drawn; however, whenever
  15. 'a Globe intersects the Text, FBSpriteWorld must render at least a
  16. 'part of the Text Sprite, and this causes the animation to slow down.
  17. 'This slowing is only noticeable because most of the Globe Sprites
  18. 'are moved 'as quickly as possible.'  If this were anything other
  19. 'than a demo, we would assign move times to each Globe Sprite suf-
  20. 'ficient to keep them moving at a steady pace.
  21.  
  22. 'We can learn several lessons from the 'slowing' phenomenon: namely,
  23. 'keep the number of Sprites to a minimum, keep the number of moving
  24. 'Sprites as small as possible, avoid intersecting inactive Sprites,
  25. 'and for optimum performance, keep the Sprites small.  If you must
  26. 'have large Sprites, try to make them wide rather than tall.
  27.  
  28. 'When you click the mouse button to exit this program, an Alert will
  29. 'display showing the number of animation frames performed per second.
  30. 'On my original Mac LC, I get about 14.5 frames per second.  The 
  31. 'C version of SpriteWorld by Tony Myles clocks a cool 22 frames per
  32. 'second using CopyBits, and 30+ with an assembly bit blitter!  Such
  33. 'figures indicate we've got a long way to go with improving the 
  34. 'animation engine - any ideas out there?
  35.  
  36. 'Disclaimer:  I've tested these routines quite thoroughly on my Mac
  37. 'LC running System 7.01 and FB 1.02c.  I make no promises or warranties 
  38. 'of any kind.
  39. '*********************************************************************
  40.  
  41. COMPILE 0, _MacsBugLabels _caseInsensitive
  42. RESOURCES "FBSpriteWorld.RSRC"
  43.  
  44. '---------------------------- GLOBALS --------------------------------
  45.  
  46. GLOBALS "GraphicUtils.glbl"
  47. GLOBALS "FBSpriteWorld.glbl"
  48.  
  49. _backPatRSRC=129
  50. _spriteGlobeRSRC=132
  51. _spriteTextRSRC=228
  52.  
  53. END GLOBALS
  54.  
  55. GOTO "Main"
  56.  
  57. '--------------------------- INCLUDES --------------------------------
  58.  
  59. INCLUDE "FBSpriteWorld.incl"
  60.  
  61. '------------------------- ERROR HANDLER -----------------------------
  62.  
  63. CLEAR LOCAL
  64. LOCAL FN FatalError(errCode)
  65.    'Simple error handler.  You'll want to improve on this in your
  66.    'program...
  67.    
  68.    LONG IF errCode<>_noErr
  69.       SELECT errCode
  70.          CASE _swTooManyLayers:errStr$="Out of Memory."
  71.          CASE _swTooManySprites:errStr$="Too many Sprites."
  72.          CASE _swTooManyFrames:errStr$="Too many Frames."
  73.          CASE _swNotSystemSeven:errStr$="SpriteWorld requires System 7!"
  74.          CASE _swTimeMgrNotPresent:errStr$="SpriteWorld requires Time Manager."
  75.          CASE _swOutOfMemory:errStr$="Out of Memory."
  76.          CASE ELSE
  77.             errStr$="Unknown error."
  78.       END SELECT
  79.       
  80.       tmp$="Error Code:"+STR$(errCode)
  81.       CALL PARAMTEXT(errStr$,tmp$,"","")
  82.       x=FN STOPALERT(1,0)
  83.       END
  84.    END IF
  85. END FN
  86.  
  87. '------------------------ SPRITEWORLD PROCS --------------------------
  88.  
  89. "SWBounceMoveProc"
  90. ENTERPROC(SWPtr&,spritePtr&,curRectPtr&)
  91.    'standard bounce movement proc.  Keeps sprite inside sprite boundsRect
  92.    
  93.    LONG IF curRectPtr&.left%+spritePtr&.xDelta%<=spritePtr&.sBoundsRect.left%
  94.       spritePtr&.xDelta%=spritePtr&.xDelta%*-1
  95.    XELSE
  96.       LONG IF curRectPtr&.right%+spritePtr&.xDelta%>=spritePtr&.sBoundsRect.right%
  97.          spritePtr&.xDelta%=spritePtr&.xDelta%*-1
  98.       END IF
  99.    END IF
  100.    LONG IF curRectPtr&.top%+spritePtr&.yDelta%<=spritePtr&.sBoundsRect.top%
  101.       spritePtr&.yDelta%=spritePtr&.yDelta%*-1
  102.    XELSE
  103.       LONG IF curRectPtr&.bottom%+spritePtr&.yDelta%>=spritePtr&.sBoundsRect.bottom%
  104.          spritePtr&.yDelta%=spritePtr&.yDelta%*-1
  105.       END IF
  106.    END IF
  107. EXITPROC
  108. RETURN
  109.  
  110. "SWTimeTask"
  111. 'Sets the frameTTHasFired or moveTTHasFired field of the sprite record
  112. 'to _zTrue (-1).  Called by the Time Manager if frameTimeInterval or
  113. 'moveTimeInterval field of sprite record > 0.
  114.  
  115. `                 move.w      #-1,tmXQSize(a1)  ;[move|frame]TTHasFired=_zTrue
  116. `                 rts                           ;return
  117.  
  118. '-------------------------- MAIN LOOP --------------------------------
  119.  
  120. "Main"
  121. DIM wRect.8,curRect.8
  122. DIM mySW.SpriteWorldRec
  123. DIM myLayer.SWLayerRec(1)
  124. DIM textLayer.SWLayerRec
  125. DIM mySprite.SWSpriteRec(3)
  126. DIM textSprite.SWSpriteRec
  127. DIM myFrame.SWFrameRec(9)
  128. DIM textFrame.SWFrameRec
  129. DIM wndPort&               
  130.  
  131. CURSOR _watchCursor                               'takes a few seconds to set up
  132.  
  133. '--------------------------------------------------------------------
  134. 'Initialization and Set Up
  135. '--------------------------------------------------------------------
  136.  
  137. 'Can we run in this environment?
  138. err=FN SWEnterSpriteWorld
  139. FN FatalError(err)
  140.  
  141. 'Open a window and draw pretty background
  142. pat&=FN GETPIXPAT(_backPatRSRC)                   'get pattern RSRC
  143. wWidth=SYSTEM(_scrnWidth)                         'screen width
  144. wHeight=SYSTEM(_scrnHeight)                       'screen height
  145. CALL SETRECT(wRect,0,40,wWidth,wHeight)           'set window Rect
  146. 'CALL SETRECT (wRect, 1050,30,1700,400)
  147. WINDOW #1,"Spinning Globe",@wRect,5               'open a window the same size as wRect
  148. wndPort&=FN GetCurrPort                           'get grafPtr
  149. CALL FILLCRECT(#wndPort&+_portRect,pat&)          'fill with nice pattern
  150.  
  151. '// NOTE:  At this point, it would be easier to create the      //
  152. '// SpriteWorld based on the window port by using               //
  153. '// SWCreateSWFromWindow, as we have in the other examples.     //
  154. '// However, here we'll create the SpriteWorld from 'scratch'   //
  155. '// with our own background PICT and bounding rectangle.  This  //
  156. '// is the technique you would use to create a SpriteWorld with //
  157. '// a bounding rectangle smaller than the window's PortRect, or //
  158. '// to use a background different than the current background   //
  159. '// of the window.                                              //
  160.  
  161. pict&=USR GETPICT(#wndPort&+_portRect)            'take pict of screen
  162.  
  163. 'Create SpriteWorld
  164. err=FN SWCreateSpriteWorld(@mySW,wndPort&,wndPort&+_portRect,pict&)
  165. FN FatalError(err)
  166.  
  167. 'get time task ptr (same for all sprites)
  168. ttPtr&=LINE "SWTimeTask"
  169.  
  170. '--------------------------------------------------------------------
  171. 'Create Globe Sprites
  172. '--------------------------------------------------------------------
  173.  
  174. 'get moveProc ptr (same for all sprites)
  175. movePtr&=LINE "SWBounceMoveProc"
  176.  
  177. 'create first globe sprite
  178. err=FN SWSpriteFromPict(@mySprite(0),0,0,0,wndPort&+_portRect,_zTrue,2,2,-1,ttPtr&,movePtr&,_spriteGlobeRSRC)
  179. FN FatalError(err)
  180.  
  181. 'add frames to globe sprite (add frames before clonning!)
  182. FOR x=0 TO 9
  183.    err=FN SWFrameFromPict(@myFrame(x),_spriteGlobeRSRC+(x*3))
  184.    FN FatalError(err)
  185.    err=FN SWAddFrameToSprite(@mySprite(0),@myFrame(x))
  186.    FN FatalError(err)
  187. NEXT
  188.  
  189. 'clone sprite(0) to make sprites 1-3
  190. FOR x=1 TO 3
  191.    FN SWCloneSprite(@mySprite(0),@mySprite(x),ttPtr&)
  192. NEXT
  193.  
  194. 'set sprite locations for sprites 1-3
  195. FN SWSetSpriteLocation(@mySprite(1),465,0)
  196. FN SWSetSpriteLocation(@mySprite(2),465,290)
  197. FN SWSetSpriteLocation(@mySprite(3),0,290)
  198.  
  199. 'change sprite frame advance for sprites 1 and 3
  200. FN SWSetSpriteFrameAdv(@mySprite(1),1)
  201. FN SWSetSpriteFrameAdv(@mySprite(3),1)
  202.  
  203. 'change sprite move delta for sprites 0 and 2
  204. FN SWSetMoveDelta(@mySprite(0),1,1)
  205. FN SWSetMoveDelta(@mySprite(2),6,6)
  206.  
  207. 'set sprite move time for sprite 0 (all others will move as fast as they can)
  208. FN SWSetMoveTime(@mySprite(0),500)
  209. 'set sprite frame time for sprite 1 (all others will advance frames as fast as they can)
  210. FN SWSetFrameTime(@mySprite(1),150)
  211.  
  212. '--------------------------------------------------------------------
  213. 'Create Text Sprite
  214. '--------------------------------------------------------------------
  215.  
  216. '// NOTE:  Normally, we use SWSpriteFromPict to create a sprite   //
  217. '// that is based on a PICT resource, like our text sprite.  For  //
  218. '// purposes of demonstration, we'll create this sprite from      //
  219. '// 'scratch,' by calling SWInitSprite instead.  We'll extract    //
  220. '// frameRect from the PICT resource, move it where we want it,   //
  221. '// then pass it to the initialization routine.  SWInitSprite     //
  222. '// would be most useful if you were making a sprite from some-   //
  223. '// thing other than a PICT resource, such as an object drawn on  //
  224. '// the screen.                                                       // 
  225.  
  226. 'create frame first so we can easily get its rect
  227. err=FN SWFrameFromPict(@textFrame,_spriteTextRSRC)
  228. FN FatalError(err)
  229.  
  230. 'get frame rect
  231. BLOCKMOVE @textFrame+_fBoundsRect,@curRect,8
  232.  
  233. 'center it in window rect
  234. FN CenterRect(curRect,wndPort&.portRect&)
  235.  
  236. 'create text sprite
  237. FN SWInitSprite(@textSprite,0,@curRect,wndPort&+_portRect,_zTrue,0,0,0,ttPtr&,movePtr&)
  238.  
  239. 'set move and frame times to -1 (no frame advance or movement)
  240. FN SWSetMoveTime(@textSprite,-1)
  241. FN SWSetFrameTime(@textSprite,-1)
  242.  
  243. 'add frame to text sprite
  244. err=FN SWAddFrameToSprite(@textSprite,@textFrame)
  245. FN FatalError(err)
  246.  
  247. '---------------------------------------------------------------------
  248. 'Assemble the Pieces
  249. '---------------------------------------------------------------------
  250.  
  251. 'add globe sprites to globe layer 0
  252. err=FN SWAddSpriteToLayer(@myLayer(0),@mySprite(0))
  253. FN FatalError(err)
  254. err=FN SWAddSpriteToLayer(@myLayer(0),@mySprite(1))
  255. FN FatalError(err)
  256.  
  257. 'add text sprite to text layer 
  258. err=FN SWAddSpriteToLayer(@textLayer,@textSprite)
  259. FN FatalError(err)
  260.  
  261. 'add globe sprites to globe layer 1
  262. err=FN SWAddSpriteToLayer(@myLayer(1),@mySprite(2))
  263. FN FatalError(err)
  264. err=FN SWAddSpriteToLayer(@myLayer(1),@mySprite(3))
  265. FN FatalError(err)
  266.  
  267. 'add layers to world
  268. err=FN SWAddLayerToWorld(@mySW,@myLayer(0))
  269. FN FatalError(err)
  270. err=FN SWAddLayerToWorld(@mySW,@textLayer)
  271. FN FatalError(err)
  272. err=FN SWAddLayerToWorld(@mySW,@myLayer(1))
  273. FN FatalError(err)
  274.  
  275. '---------------------------------------------------------------------
  276. 'Final Set Up
  277. '---------------------------------------------------------------------
  278.  
  279. 'Prepare loadframe for animation
  280. FN SWRefreshBackground(@mySW)
  281.  
  282. CURSOR _arrowCursor                               'we're ready to go...
  283.  
  284. 'Render 1st frame of animation
  285. FN SWAnimateSpriteWorld(@mySW)
  286.  
  287. '---------------------------------------------------------------------
  288. 'Animation Loop
  289. '---------------------------------------------------------------------
  290.  
  291. a&=TIMER:frames&=0                                'set initial timer vars
  292. DO
  293.    FN SWProcessSpriteWorld(@mySW)                 'move sprites
  294.    FN SWAnimateSpriteWorld(@mySW)                 'render sprites
  295.    CALL SYSTEMTASK                                'be kind to system
  296.    INC(frames&)                                   'keep track of animation frames
  297. UNTIL FN BUTTON
  298.  
  299. '---------------------------------------------------------------------
  300. 'Report Animation Speed
  301. '---------------------------------------------------------------------
  302.  
  303. 'How'd we do?
  304. elapsedTime&=TIMER-a&
  305. a$=STR$(frames&)+" frames drawn in"+STR$(elapsedTime&)+" secs."
  306. b$="Average: "+LEFT$(STR$(frames&\elapsedTime&),6)+" frames per second."
  307. CALL PARAMTEXT(a$,b$,"","")
  308. x=FN NOTEALERT(1,0)
  309.  
  310. '---------------------------------------------------------------------
  311. 'Dispose SpriteWorld and Exit
  312. '---------------------------------------------------------------------
  313.  
  314. err=FN SWDisposSpriteWorld(@mySW)
  315. FN FatalError(err)
  316.  
  317. END
  318.  
  319.